package com.hanlin.backend.common.aspect;

import com.hanlin.backend.common.util.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 描述：
 *
 * @author:hl.yuan
 * @date:2021-03-29
 */
@Component
@Aspect
@Slf4j
public class MyAdvice {


    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    /**
     * 定义切点
     */
    @Pointcut("@annotation(com.hanlin.backend.common.annotation.ModelSubmit)")
    private void pc() {
    }

    /**
     * 指定该方法是前置通知，并指定切入点
     */
    @Before("MyAdvice.pc()")
    public void before() {
    }

    /**
     * 后置通知
     */
    @AfterReturning("MyAdvice.pc()")
    public void afterReturning() {
    }

    /**
     * 环绕通知
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("MyAdvice.pc()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        // 1.从redis中获取主数据库，若获取不到直接退出，否则判断当前数据源是会否为主，若不为主，则切换到主数据源
        // 2.调用目标方法
        Object proceed = pjp.proceed();
        // 3.获取SQL
        String sql = SqlUtils.getMybatisSql(pjp, sqlSessionFactory);
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        String namespace = method.getDeclaringClass().getName();
        String methodName = method.getName();
        // 4.打印SQL语句
        log.info("【SQL语句打印 {}.{}】： {}}", namespace, methodName, sql);
        // 5.通知同步程序
        return proceed;
    }

    /**
     * 异常通知
     */
    @AfterThrowing("MyAdvice.pc()")
    public void afterException() {
    }

    /**
     * 后置通知
     */
    @After("MyAdvice.pc()")
    public void after() {
    }
}
